compact_optional.hpp
namespace type_safe
{
template <class CompactPolicy>
class compact_optional_storage;
template <class CompactPolicy>
using compact_optional = basic_optional<compact_optional_storage<CompactPolicy>>;
template <typename Boolean>
class compact_bool_policy;
template <typename Integer, Integer Invalid>
class compact_integer_policy;
template <typename FloatingPoint>
class compact_floating_point_policy;
template <typename Enum, 'hidden' Invalid>
class compact_enum_policy;
template <class Container>
class compact_container_policy;
}
type_safe::compact_optional_storage
[optional]template <class CompactPolicy>
class compact_optional_storage
{
public:
using value_type = typename std::remove_cv<typename CompactPolicy::value_type>::type;
using storage_type = typename CompactPolicy::storage_type;
using lvalue_reference = 'hidden';
using const_lvalue_reference = 'hidden';
using rvalue_reference = 'hidden';
using const_rvalue_reference = 'hidden';
template <typename U>
using rebind = direct_optional_storage<U>;
compact_optional_storage() noexcept;
template <typename ... Args>
typename std::enable_if<std::is_constructible<value_type, Args&&...>::value>::type create_value(Args&&... args);
void create_value(const compact_optional_storage& other);
void create_value(compact_optional_storage&& other);
void create_value_explicit();
void copy_value(const compact_optional_storage& other);
void copy_value(compact_optional_storage&& other);
void swap_value(compact_optional_storage& other);
void destroy_value() noexcept;
bool has_value() const noexcept;
lvalue_reference get_value() & noexcept;
const_lvalue_reference get_value() const & noexcept;
rvalue_reference get_value() && noexcept;
const_rvalue_reference get_value() const && noexcept;
template <typename U, typename = typename std::enable_if<std::is_copy_constructible<value_type>::value&&std::is_convertible<U&&, value_type>::value>::type>
value_type get_value_or(U&& u) const &;
template <typename U>
value_type get_value_or(U&& u) &&;
};
A StoragePolicy
for ts::basic_optional that is more space efficient than ts::direct_optional_storage.
It is designed to have no space overhead compared to a regular object of the stored type. This is accomplished by marking one value of the stored type as invalid and using that in the empty state. What the invalid value is is controlled by the CompactPolicy
. It must provide the following static
member functions and typedefs:
value_type
- the value that is being stored conceptuallystorage_type
- the actual type that is being storedstorage_type invalid_value()
- returns the value that marks the optional as emptybool is_invalid(const storage_type&)
- returns true
if the given value is invalid, false
otherwiseIn the cases where value_type
and storage_type
differ, the get_value()
functions will not return references, but a copy instead. The implementation assumes that invalid_value()
and is_invalid()
are noexcept
and cheap.
Notes: For a compact optional of pointer type, use ts::optional_ref.
type_safe::compact_optional_storage::compact_optional_storage
compact_optional_storage() noexcept;
Effects: Initializes it in the state without value, i.e. sets the storage to the invalid value.
type_safe::compact_optional_storage::create_value
template <typename ... Args>
typename std::enable_if<std::is_constructible<value_type, Args&&...>::value>::type create_value(Args&&... args);
Effects: Creates a temporary value_type
by perfectly forwarding args
, converts that to the storage_type
and assigns it. Afterwards has_value()
will return true
.
Throws: Anything thrown by the constructor of value_type
/storage_type
or its move assignment operator in which case has_value()
is still false
. \requires has_value() == false
and the given value must not be invalid. \notes This function does not participate in overload resolution unless value_type
is constructible from args
. \synopsis template
type_safe::compact_optional_storage::create_value
void create_value(const compact_optional_storage& other);
Effects: Copy assigns the storage_type
.
type_safe::compact_optional_storage::create_value
void create_value(compact_optional_storage&& other);
Effects: Move assigns the storage_type
.
type_safe::compact_optional_storage::copy_value
void copy_value(const compact_optional_storage& other);
Effects: Copy assigns the storage_type
.
type_safe::compact_optional_storage::copy_value
void copy_value(compact_optional_storage&& other);
Effects: Move assigns the storage_type
.
type_safe::compact_optional_storage::swap_value
void swap_value(compact_optional_storage& other);
Effects: Swaps the storage_type
.
type_safe::compact_optional_storage::destroy_value
void destroy_value() noexcept;
Effects: Destroys the value by setting it to the invalid storage value. Afterwards has_value()
will return false
.
Requires: has_value() == true
.
type_safe::compact_optional_storage::has_value
bool has_value() const noexcept;
Returns: Whether or not there is a value stored, i.e. whether the stored value is not invalid.
type_safe::compact_optional_storage::get_value
(1) lvalue_reference get_value() & noexcept;
(2) const_lvalue_reference get_value() const & noexcept;
(3) rvalue_reference get_value() && noexcept;
(4) const_rvalue_reference get_value() const && noexcept;
Returns: A (suitable) reference to the stored value or a copy of the value depending on the policy.
Requires: has_value() == true
.
type_safe::compact_optional_storage::get_value_or
template <typename U, typename = typename std::enable_if<std::is_copy_constructible<value_type>::value&&std::is_convertible<U&&, value_type>::value>::type>
value_type get_value_or(U&& u) const &;
Returns: Either get_value()
or u
converted to value_type
.
Requires: value_type
must be copy (1)/move (2) constructible and u
convertible to value_type
. \group get_value_or \param 1 \exclude
type_safe::compact_optional_storage::get_value_or
(1) template <typename U>
value_type get_value_or(U&& u) &&;
type_safe::compact_optional
template <class CompactPolicy>
using compact_optional = basic_optional<compact_optional_storage<CompactPolicy>>;
An alias for ts::basic_optional using ts::compact_optional_storage with the given CompactPolicy
. \module optional
type_safe::compact_bool_policy
template <typename Boolean>
class compact_bool_policy
{
public:
using value_type = Boolean;
using storage_type = char;
static storage_type invalid_value() noexcept;
static bool is_invalid(storage_type storage) noexcept;
};
A CompactPolicy
for ts::compact_optional_storage for boolean types.
It is designed for either bool
or ts::boolean.
Notes: It uses a different storage_type
and thus cannot return a reference to the stored value. \module optional
type_safe::compact_integer_policy
template <typename Integer, Integer Invalid>
class compact_integer_policy
{
public:
using value_type = Integer;
using storage_type = Integer;
static storage_type invalid_value() noexcept;
static bool is_invalid(const storage_type& storage) noexcept;
};
A CompactPolicy
for ts::compact_optional_storage for integer types.
The given Invalid
value will be used to mark an empty optional.
type_safe::compact_floating_point_policy
[optional]template <typename FloatingPoint>
class compact_floating_point_policy
{
public:
using value_type = FloatingPoint;
using storage_type = FloatingPoint;
static storage_type invalid_value() noexcept;
static bool is_invalid(const storage_type& storage) noexcept;
};
A CompactPolicy
for ts::compact_optional_storage for floating point types.
NaN
will be used to mark an empty optional.
type_safe::compact_enum_policy
template <typename Enum, 'hidden' Invalid>
class compact_enum_policy
{
public:
using value_type = Enum;
using storage_type = 'hidden';
static storage_type invalid_value() noexcept;
static bool is_invalid(const storage_type& storage) noexcept;
};
A CompactPolicy
for ts::compact_optional_storage for enumeration types.
It uses the given Invalid
value of the underlying type to mark an empty optional.
Notes: It uses a different storage_type
and thus cannot return a reference to the stored value. \module optional
type_safe::compact_container_policy
template <class Container>
class compact_container_policy
{
public:
using value_type = Container;
using storage_type = Container;
static storage_type invalid_value() noexcept;
static bool is_invalid(const storage_type& storage) noexcept;
};
A CompactPolicy
for ts::compact_optional_storage for container types.
A Container
is a type with a cheap no-throwing default constructor initializing it empty, and either an empty()
member function or ADL function that returns true
if the container is empty, false
otherwise. An empty container will be marked as an empty optional. \module optional